package com.xingu.xg.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.xingu.xg.common.enums.LevelEnum;
import com.xingu.xg.common.enums.OrderByEnum;
import com.xingu.xg.po.query.*;
import com.xingu.xg.po.vo.PartSaveReqVO;
import com.xingu.xg.po.vo.PartTreeNode;
import com.xingu.xg.po.vo.PartUpdateReqVO;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xingu.xg.mapper.PartMapper;
import com.xingu.xg.po.Part;
import com.xingu.xg.service.PartService;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class PartServiceImpl extends ServiceImpl<PartMapper, Part> implements PartService {

    @Resource
    private PartMapper partMapper;

    @Override
    public void createPart(PartSaveReqVO reqVO) {
        int orderNum = getOrderNum(reqVO.getParentId());

        Part part = BeanUtil.copyProperties(reqVO, Part.class);
        part.setOrderNum(orderNum);
        partMapper.insert(part);
    }

    @Override
    public void updatePartById(PartUpdateReqVO reqVO) {
        Part part = BeanUtil.copyProperties(reqVO, Part.class);
        partMapper.updateById(part);
    }


    @Override
    public List<PartTreeNode> getTreeList() {
        List<Part> partList = partMapper.selectList(null);

        List<PartTreeNode> list = BeanUtil.copyToList(partList, PartTreeNode.class);

        if (CollectionUtil.isNotEmpty(list)) {
            return list.stream()
                    .filter(item -> 0 == item.getParentId())
                    .sorted(Comparator.comparing(PartTreeNode::getOrderNum).thenComparing(PartTreeNode::getId))
                    .peek(item -> item.setChildren(getChildren(item, list)))
                    .collect(Collectors.toList());
        }

        return list;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void createPeer(AddPeerNodeQuery query) {
        // 根据选中节点id查询当前节点
        Part part = partMapper.selectById(query.getSelectedId());
        Long parentId = part.getParentId();
        Integer orderNum = part.getOrderNum();

        // 创建同级节点
        Part newPart = new Part();
        newPart.setParentId(parentId);
        newPart.setName(query.getName());
        newPart.setOrderNum(orderNum);
        partMapper.insert(newPart);

        // 获取排序编号大于当前节点的列表
        List<Part> next = getNextNodeList(parentId, orderNum);

        if (OrderByEnum.UP.equals(query.getOrderByEnum())) {
            next.add(part);
        } else {
            next.add(newPart);
        }

        // 下级节点重排序
        if (CollectionUtil.isNotEmpty(next)) {
            List<Long> ids = next.stream().map(Part::getId).collect(Collectors.toList());
            partMapper.updateOrderNum(ids, orderNum);
        }
    }

    /**
     * 获取排序编号大于当前节点的列表
     *
     * @param parentId 父id
     * @param orderNum 排序编号
     * @return {@link Part }
     */
    private List<Part> getNextNodeList(Long parentId, Integer orderNum) {
        LambdaQueryWrapper<Part> queryWrapper = new LambdaQueryWrapper<Part>()
                .eq(Part::getParentId, parentId)
                .gt(Part::getOrderNum, orderNum)
                .orderByAsc(Part::getOrderNum);
        return partMapper.selectList(queryWrapper);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void createUpDown(AddUpDownNodeQuery query) {
        // 根据选中节点id查询父节点
        Part part = partMapper.selectById(query.getSelectedId());
        Long parentId = part.getParentId();

        if (LevelEnum.UP.equals(query.getLevelEnum())) {
            // 创建同级节点
            Part upPart = new Part();
            upPart.setParentId(parentId);
            upPart.setName(query.getName());
            upPart.setOrderNum(this.getOrderNum(parentId));
            partMapper.insert(upPart);

            // 把当前节点移入新节点的子节点
            part.setParentId(upPart.getId());
            partMapper.updateById(part);
        } else {
            // 创建下级节点
            Part downPart = new Part();
            downPart.setParentId(part.getId());
            downPart.setName(query.getName());
            downPart.setOrderNum(this.getOrderNum(part.getId()));
            partMapper.insert(downPart);
        }

    }

    @Override
    public void copyNode(CopyNodeQuery query) {
        // 根据选中节点id查询节点
        Part part = partMapper.selectById(query.getSelectedId());

        List<CopyNodeData> list = query.getList();
        // 选中节点ids
        List<Long> originalParentIds = list.stream().map(CopyNodeData::getOriginalId).collect(Collectors.toList());

        // 过滤出选中的父节点
        List<Long> originalIds = list.stream().filter(item -> !originalParentIds.contains(item.getOriginalParentId())).map(CopyNodeData::getOriginalId).collect(Collectors.toList());

        // 修改复制节点到选中节点下
        LambdaQueryWrapper<Part> queryWrapper = new LambdaQueryWrapper<Part>()
                .in(Part::getId, originalIds);
        Part updatePart = new Part();
        updatePart.setParentId(part.getId());
        partMapper.update(updatePart, queryWrapper);

    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deleteNode(DeleteNodeQuery query) {
        query.getDeleteList().forEach(id -> {
            // 根据id查询节点父id
            Part part = partMapper.selectById(id);

            // 根据选中节点id查询是否有子节点
            LambdaQueryWrapper<Part> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(Part::getParentId, id);
            List<Part> childrenList = partMapper.selectList(queryWrapper);

            if (CollectionUtil.isNotEmpty(childrenList)) {
                // 有子节点，修改子节点的父级id为选中节点的父级id
                LambdaQueryWrapper<Part> updateQueryWrapper = new LambdaQueryWrapper<Part>()
                        .in(Part::getParentId, id);
                Part updatePart = new Part();
                updatePart.setParentId(part.getParentId());
                partMapper.update(updatePart, updateQueryWrapper);
            }
        });

        // 删除选中节点
        partMapper.deleteBatchIds(query.getDeleteList());
    }

    /**
     * 构建子节点
     *
     * @param root 根
     * @param all  全部
     * @return {@link List }<{@link PartTreeNode }>
     */
    private List<PartTreeNode> getChildren(PartTreeNode root, List<PartTreeNode> all) {
        return all.stream()
                .filter(item -> item.getParentId().equals(root.getId()))
                .sorted(Comparator.comparing(PartTreeNode::getOrderNum))
                .peek(item -> item.setChildren(getChildren(item, all)))
                .collect(Collectors.toList());
    }

    /**
     * 获取排序编号
     *
     * @param parentId 父id
     * @return int
     */
    private int getOrderNum(Long parentId) {
        int orderNum = 1;
        if (ObjUtil.isNotEmpty(parentId)) {
            // 根据父节点id查询同级最大排序号
            LambdaQueryWrapper<Part> queryWrapper = new LambdaQueryWrapper<Part>()
                    .eq(Part::getParentId, parentId)
                    .orderByDesc(Part::getOrderNum)
                    .last("limit 1");
            Part part = partMapper.selectOne(queryWrapper);
            if (ObjUtil.isNotEmpty(part)) {
                orderNum = part.getOrderNum() + 1;
            }
        }
        return orderNum;
    }
}
